package top.someapp.dxf2dsvg.entity;

import top.someapp.dxf2dsvg.base.Point;
import top.someapp.dxf2dsvg.dxf.Item;
import top.someapp.dxf2dsvg.kits.Nulls;

import javax.annotation.Nonnull;
import java.lang.reflect.Constructor;
import java.util.Hashtable;
import java.util.Map;

/**
 * @author zwz
 * Created on 2020-04-20
 * @see <a href="http://help.autodesk.com/view/OARX/2018/CHS/?guid=GUID-7D07C886-FD1D-4A0C-A7AB-B4D21F18E484">
 * 关于 DXF ENTITIES 段</a>
 */
public class Entities {
    private Entities() {
        // prevent outer new instance
    }

    static class EntityBlank extends EntityBase {
        @Override
        public String type() {
            return "";
        }

        @Override
        public void setBasePoint(@Nonnull Point basePoint) {
            // blank entity do nothing!!
        }

        @Override
        public void setup(@Nonnull Item item) {
            // blank entity do nothing!!
        }
    }

    private static final Entity blankEntity = new EntityBlank();
    private static final Map<String, Constructor<? extends Entity>> entityClasses = new Hashtable<>();

    private static void init() {
        if (!entityClasses.isEmpty())
            return;

        try {
            Constructor<? extends Entity> defaultConstructor = EntityBlank.class.getDeclaredConstructor();
            entityClasses.put("ARC", Arc.class.getDeclaredConstructor());
            entityClasses.put("CIRCLE", Circle.class.getDeclaredConstructor());
//        entityClasses.put("DIMENSION", EntityBlank.class);
//        entityClasses.put("ELLIPSE", EntityBlank.class);
//        entityClasses.put("HATCH", EntityBlank.class);
//        entityClasses.put("HELIX", EntityBlank.class);
//        entityClasses.put("IMAGE", EntityBlank.class);
            entityClasses.put("INSERT", Insert.class.getDeclaredConstructor());
//        entityClasses.put("LEADER", EntityBlank.class);
//        entityClasses.put("LIGHT", EntityBlank.class);
            entityClasses.put("LINE", Line.class.getDeclaredConstructor());
//            entityClasses.put("LWPOLYLINE", defaultConstructor);
//        entityClasses.put("MESH", EntityBlank.class);
//            entityClasses.put("MLINE", defaultConstructor);
//        entityClasses.put("MLEADERSTYLE", EntityBlank.class);
//        entityClasses.put("MLEADER", EntityBlank.class);
//            entityClasses.put("MTEXT", defaultConstructor);
//        entityClasses.put("OLEFRAME", EntityBlank.class);
//        entityClasses.put("OLE2FRAME", EntityBlank.class);
//            entityClasses.put("POINT", defaultConstructor);
//            entityClasses.put("POLYLINE", defaultConstructor);
//        entityClasses.put("RAY", EntityBlank.class);
//        entityClasses.put("REGION", EntityBlank.class);
//        entityClasses.put("SECTION", EntityBlank.class);
//        entityClasses.put("SEQEND", EntityBlank.class);
//        entityClasses.put("SHAPE", EntityBlank.class);
//            entityClasses.put("SOLID", defaultConstructor);
//            entityClasses.put("SPLINE", defaultConstructor);
//        entityClasses.put("SUN", EntityBlank.class);
//        entityClasses.put("SURFACE", EntityBlank.class);
//        entityClasses.put("TABLE", EntityBlank.class);
//            entityClasses.put("TEXT", defaultConstructor);
//        entityClasses.put("TOLERANCE", EntityBlank.class);
//        entityClasses.put("TRACE", EntityBlank.class);
//        entityClasses.put("UNDERLAY", EntityBlank.class);
//        entityClasses.put("VERTEX", EntityBlank.class);
//        entityClasses.put("VIEWPORT", EntityBlank.class);
//        entityClasses.put("WIPEOUT", EntityBlank.class);
//            entityClasses.put("XLINE", defaultConstructor);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    public static Entity make(@Nonnull String type) {
        init();
        Entity entity = null;
        if (entityClasses.containsKey(type)) {
            try {
                entity = entityClasses.get(type).newInstance();
            } catch (ReflectiveOperationException e) {
                e.printStackTrace();
            }
        }
        return Nulls.firstNonNull(entity, blankEntity);
    }
}
